﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Janus.Cores.Configuration;
namespace Janus.Cores.Files
{
    /// <summary>
    /// <see cref="IFileHandler"/>文件存储实现
    /// </summary>
    internal class FileHandler : IFileHandler {
       
        /// <summary>
        /// 保存文件的路径
        /// </summary>
        public  string ShortPath { get; set; }

        /// <summary>
        /// 保存文件的路径包含文件名
        /// </summary>
        public  string FullPath { get; set; }

        ///// <summary>
        ///// 将一个文件存储到系统中
        ///// </summary>
        ///// <param name="file">文件路径</param>
        ///// <returns>存储完毕的实际文件名称，文件名称会重新生成</returns>
        //public string SaveFile(string file,string folder)
        //{
        //    return SaveFile(file,string.Empty,true);
        //}

        /// <summary>
        /// 将一个文件存储到系统中
        /// </summary>
        /// <param name="file">文件路径</param>
        /// <param name="rename">是否重新命名文件</param>
        /// <param name="folder">文件夹</param>
        /// <returns>存储完毕的实际文件名称</returns>
        public string SaveFile(string file, string folder, bool rename) {
            var fileinfo = new FileInfo(file);
            if (!fileinfo.Exists)
                throw new FileNotFoundException(file);
            string newfile;

            var fullFileName = GetAbsolutePath(fileinfo.Name, folder, rename, out newfile);

            fileinfo.CopyTo(fullFileName, true);

            if (rename)
                return newfile;
            else
                return fileinfo.Name;
        }

        /// <summary>
        /// 将一个文件流存储到系统中
        /// </summary>
        /// <param name="fileName">文件名称</param>
        /// <param name="inputStream">文件流</param>
        /// <param name="rename">是否重新命名</param>
        /// <param name="folder">文件夹</param>
        /// <returns></returns>
        public string SaveFile(string fileName, string folder, System.IO.Stream inputStream, bool rename) {
            string newfile;

            var fullFileName = GetAbsolutePath(fileName, folder, rename, out newfile);

            using (var sw = new FileStream(fullFileName, FileMode.OpenOrCreate, FileAccess.Write)) {
                using (var sr = new BufferedStream(inputStream)) {
                    var buff = new byte[1024];
                    while (sr.CanSeek) {
                        var len = sr.Read(buff, 0, 1024);
                        sw.Write(buff, 0, len);
                        if (len < 1024)
                            break;
                    }
                }
                sw.Flush();
                sw.Close();
            }
            return newfile;
        }

        /// <summary>
        /// 打开一个文件流
        /// </summary>
        /// <param name="name">文件名称</param>
        /// <returns>文件流</returns>
        public System.IO.Stream OpenFile(string name) {
            return OpenFile(name, FileMode.Open);
        }

        public Stream OpenFile(string name, FileMode mode) {
            string fileName = Path.GetFileName(name);
            string folder = Path.GetDirectoryName(name);

            var path = GetPath(folder, true);
            var file = Path.Combine(path, fileName);
            if (FileMode.OpenOrCreate == mode
                || mode == FileMode.CreateNew
                || mode == FileMode.Create)
                return new FileStream(file, mode, FileAccess.Write);

            if (FileMode.Append == mode) {
                if (File.Exists(file))
                    return new FileStream(file, mode, FileAccess.Write);
                else
                    return null;
            }

            if (File.Exists(file))
                return new FileStream(file, mode, FileAccess.ReadWrite);
            else
                return null;
        }


        /// <summary>
        /// 获取文件信息
        /// </summary>
        /// <param name="name">文件名称</param>
        /// <returns>文件信息</returns>
        public FileInfomation GetFileInformation(string name) {
            var path = GetPath(string.Empty, false);
            FileInfo file;
            try {
                file = new FileInfo(Path.Combine(path, name.TrimStart('\\')));
            } catch (System.ArgumentException are) {
                throw new ArgumentException("invalide file name;" + name, are);
            }

            if (file.Exists) {
                return new FileInfomation() {
                    Name = name,
                    Exists = file.Exists,
                    Length = file.Length,
                    Extension = file.Extension,
                    LastModifyDate = file.LastWriteTimeUtc
                };
            } else {
                return new FileInfomation() {
                    Name = name,
                    Exists = file.Exists
                };
            }
        }


        /// <summary>
        /// 移除一个文件
        /// </summary>
        /// <param name="name">文件名称</param>
        /// <returns></returns>
        public bool Remove(string name) {
            var path = GetPath(string.Empty, false);
            var file = new FileInfo(Path.Combine(path, name));
            try {
                file.Delete();
                return true;
            } catch (Exception) {
                return false;
            }
        }


        private string GetPath(string subFolder, bool createFolder) {
            if (subFolder.StartsWith(@"\"))
                subFolder = subFolder.Remove(0, 1);
            var path = Path.Combine(EBSConfiguration.Current.ResouceSection.Directory, subFolder);
            this.ShortPath = path;

            if (!Directory.Exists(path) && createFolder) {
                try {
                    Directory.CreateDirectory(path);
                } catch (Exception) {
                    throw new IOException("create folder error:" + path);
                }
            }
            return path;
        }

        string GetAbsolutePath(string fileName, string folder, bool rename, out string newFileName) {
            var ext = GetFileExtendName(fileName);
            newFileName = string.Empty;
            string path = GetPath(folder, true);
            if (rename)
                newFileName = fileName = Guid.NewGuid() + "." + ext;

            this.FullPath = Path.Combine(path, fileName);
            return Path.Combine(path, fileName);
        }

        string GetFileExtendName(string fileName) {
            var temp = fileName.Split('.');
            return temp[temp.Length - 1];
        }


        public bool Rename(string oldFileName, string newFileName) {
            string fileName = Path.GetFileName(oldFileName);
            string folder = Path.GetDirectoryName(oldFileName);

            var path = GetPath(folder, true);
            var file = Path.Combine(path, fileName);
            if (!File.Exists(file))
                return false;
            string nfileName = Path.GetFileName(newFileName);
            nfileName = Path.Combine(path, nfileName);
            try {
                File.Move(file, nfileName);
                return true;
            } catch {
                return false;
            }
        }
    }
}
